package com.example.csetpp.service.impl;

import com.example.csetpp.pojo.dto.ApiTimesGetDTO;
import com.example.csetpp.pojo.vo.user.UniqueVisitorVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ApiUsageCounterService {
    private static final String API_USAGE_PREFIX = "api_usage:daily:";
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void incrementApiUsage(String url)
    {
        String key = buildKey(LocalDate.now() ,url);
        Long count = stringRedisTemplate.opsForValue().increment(key);
        if (count != null && count == 1) { // 第一次创建并计数时
            stringRedisTemplate.expire(key, 30, TimeUnit.DAYS);
        }
    }

    public UniqueVisitorVO getUV(ApiTimesGetDTO apiTimesGetDTO)
    {
        String url = apiTimesGetDTO.getUrlName();
        UniqueVisitorVO uniqueVisitorVO = new UniqueVisitorVO();
        uniqueVisitorVO.setToday(getApiUsageForToday(url));
        uniqueVisitorVO.setPastSevenDays(getApiUsageTotalForLastNDays(url,7));
        uniqueVisitorVO.setPastFifteenDays(getApiUsageTotalForLastNDays(url,15));
        return uniqueVisitorVO;
    }

    public long getApiUsageForToday(String interfaceIdentifier) {
        if (interfaceIdentifier == null || interfaceIdentifier.trim().isEmpty()) {
            return 0L;
        }
        String key = buildKey(LocalDate.now(), interfaceIdentifier);
        String countStr = stringRedisTemplate.opsForValue().get(key);
        if (countStr != null) {
            try {
                return Long.parseLong(countStr);
            } catch (NumberFormatException e) {

                return 0L;
            }
        }
        return 0L;
    }

    public long getApiUsageForDate(LocalDate date, String interfaceIdentifier) {
        if (date == null || interfaceIdentifier == null || interfaceIdentifier.trim().isEmpty()) {
            return 0L;
        }
        String key = buildKey(date, interfaceIdentifier);
        String countStr = stringRedisTemplate.opsForValue().get(key);
        if (countStr != null) {
            try {
                return Long.parseLong(countStr);
            } catch (NumberFormatException e) {
                // Log error
                return 0L;
            }
        }
        return 0L;
    }
    public long getApiUsageTotalForLastNDays(String interfaceIdentifier, int days) {
        if (interfaceIdentifier == null || interfaceIdentifier.trim().isEmpty() || days <= 0) {
            log.warn(" getApiUsageTotalForLastNDays 方法参数错误: identifier='{}', days={}", interfaceIdentifier, days);
            return 0L; // 返回0
        }

        long totalCount = 0L;
        LocalDate today = LocalDate.now();

        List<String> keysToFetch = new ArrayList<>();
        for (int i = 0; i < days; i++) {
            LocalDate date = today.minusDays(i);
            keysToFetch.add(buildKey(date, interfaceIdentifier));
        }

        // 使用 mget 批量从 Redis 获取值
        List<String> values = stringRedisTemplate.opsForValue().multiGet(keysToFetch);

        if (values != null) {
            for (int i = 0; i < values.size(); i++) {
                String valueStr = values.get(i);
                if (valueStr != null) {
                    try {
                        totalCount += Long.parseLong(valueStr);
                    } catch (NumberFormatException e) {
                        log.warn("异常: 无法获取 key '{}', value: '{}'. .", keysToFetch.get(i), valueStr, e);
                    }
                }
            }
        }

        return totalCount;
    }


    private String buildKey(LocalDate date, String interfaceIdentifier) {

        String sanitizedIdentifier = interfaceIdentifier.replace("/", "_").replace(":", "_");
        return API_USAGE_PREFIX + date.format(DATE_FORMATTER) + ":" + sanitizedIdentifier;
    }
}
